package sys

import (
	"encoding/json"
	"fmt"
	"time"

	"gitee.com/zfd81/dbrs/store"
)

type User struct {
	Name             string
	HostName         string
	Password         string
	DefaultSignature string
	CreateTime       time.Time
	ModifyTime       time.Time
}

func (u User) Save() error {
	if u.Name == "" {
		return fmt.Errorf("User name cannot be empty.")
	}
	if u.Password == "" {
		return fmt.Errorf("Password cannot be empty.")
	}
	user, err := FindUser(u.Name)
	if err != nil {
		return err
	}
	if user != nil {
		return fmt.Errorf("User already exists.")
	}

	now := time.Now()
	u.CreateTime = now
	u.ModifyTime = now

	bytes, err := json.Marshal(u)
	if err != nil {
		return err
	}
	return store.Put(store.Table_User, []byte(u.Name), bytes)
}

func (u User) Modify() error {
	if u.Name == "" {
		return fmt.Errorf("User name cannot be empty.")
	}
	user, err := FindUser(u.Name)
	if err != nil {
		return err
	}
	if user == nil {
		return fmt.Errorf("User %s does not exist.", u.Name)
	}

	user.HostName = u.HostName
	if u.Password != "" {
		user.Password = u.Password
	}
	if u.DefaultSignature != "" {
		user.DefaultSignature = u.DefaultSignature
	}
	user.ModifyTime = time.Now()

	bytes, err := json.Marshal(user)
	if err != nil {
		return err
	}
	return store.Put(store.Table_User, []byte(user.Name), bytes)
}

func DeleteUser(name string) error {
	user, err := store.Get(store.Table_User, []byte(name))
	if err != nil {
		return err
	}
	if string(user) == "" {
		return fmt.Errorf("User %s does not exist.", name)
	}
	return store.Delete(store.Table_User, []byte(name))
}

func FindUser(name string) (*User, error) {
	bytes, err := store.Get(store.Table_User, []byte(name))
	if err != nil {
		return nil, err
	}
	if bytes == nil {
		return nil, nil
	}

	user := &User{}
	err = json.Unmarshal(bytes, user)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func FindAllUsers() ([]*User, error) {
	users := []*User{}
	err := store.Iterator(store.Table_User, func(k, v []byte) error {
		user := &User{}
		err := json.Unmarshal(v, user)
		if err != nil {
			return err
		}
		users = append(users, user)
		return nil
	})
	return users, err
}

func BatchAddUsers(users []*User) error {
	for _, u := range users {
		if u != nil {
			bytes, err := json.Marshal(u)
			if err != nil {
				return err
			}
			store.Put(store.Table_User, []byte(u.Name), bytes)
		}
	}
	return nil
}

func TruncateUser() error {
	return store.Truncate(store.Table_User)
}

func NewUser(name, pwd string) *User {
	return &User{
		Name:     name,
		Password: pwd,
	}
}
